import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.LinkedList;


public class FourDMatrix extends Matrix{

	private LinkedList<FourDValueSlot> intervals;
	private LinkedList<GregorianCalendar> datas;
	
	public static void main(String[] args)
	{
		/*GregorianCalendar cal1 = new GregorianCalendar(2009, 1, 1);
		GregorianCalendar cal2 = new GregorianCalendar(2012, 1, 1);
		
		FourDMatrix matrix = new FourDMatrix();
		System.out.println(matrix.daysBetween(cal1, cal2));
		
		System.out.println(matrix.daysBetween(cal2, cal1));
		
		System.out.println(matrix.daysBetween(cal1, cal1));*/
		
		GregorianCalendar cal1 = new GregorianCalendar(2012, 6, 1);
		GregorianCalendar cal2 = new GregorianCalendar(2012, 1, 1);
		GregorianCalendar cal3 = new GregorianCalendar(2012, 2, 1);
		GregorianCalendar cal4 = new GregorianCalendar(2012, 3, 1);
		GregorianCalendar cal5 = new GregorianCalendar(2012, 4, 1);
		
		FourDMatrix fm = new FourDMatrix();
		fm.getDatas().add(cal1);
		fm.getDatas().add(cal2);
		fm.getDatas().add(cal3);
		fm.getDatas().add(cal4);
		fm.getDatas().add(cal5);
		fm.process();
		for(FourDValueSlot vs: fm.getIntervals())
		{
			System.out.println(vs.getInterval() + ": " + vs.getOccurance());
		}
		
		System.out.println("============================");
		System.out.println(fm.getAverageInterval());
		;
	}
	public FourDMatrix()
	{
		intervals = new LinkedList<FourDValueSlot>();
		datas = new LinkedList<GregorianCalendar>();
	}
	
	public LinkedList<GregorianCalendar> getDatas()
	{
		return datas;
	}
	
	public LinkedList<FourDValueSlot> getIntervals()
	{
		return intervals;
	}
	
	@Override
	public void process() {
		int size = datas.size();
		for(int i=0; i < size; i++)
		{
			for(int j=0; j< size; j++)
			{
				if(j!=i)
				{
					for(int k=0; k<size; k++)
					{
						if(k!= j && k!=i)
						{
							for(int l=0; l<size; l++)
							{
								if(l!=k && l!=j && l!=i)
								{
									int val = daysBetween(datas.get(i), datas.get(k)) + daysBetween(datas.get(j), datas.get(l));
									if(val >= 0)
									{
										insert(val);
									}
								}
							}
						}
					}
				}
			}
		}
	}
	
	public int daysBetween(GregorianCalendar calendar, GregorianCalendar calendar2)
	{
		GregorianCalendar replica1 = (GregorianCalendar) calendar.clone();
		GregorianCalendar replica2 = (GregorianCalendar) calendar2.clone();
		int result = -100;
		if(replica1.equals(replica2))
		{
			result = 0;
		}
		else if(replica1.after(replica2))
		{
			//System.out.println(calendar.getTime() + " is after " + calendar2.getTime());
			if(replica1.get(Calendar.YEAR) == replica2.get(Calendar.YEAR))
			{
				int val1 = replica1.get(Calendar.DAY_OF_YEAR);
				int val2 = replica2.get(Calendar.DAY_OF_YEAR);
				result = val1 - val2;
			}
			else
			{
				int days = 0;
				while(replica2.get(Calendar.YEAR) < replica1.get(Calendar.YEAR))
				{
					days++;
					replica2.add(Calendar.DAY_OF_YEAR, 1);
				}
			
				while(replica2.get(Calendar.DAY_OF_YEAR) < replica1.get(Calendar.DAY_OF_YEAR))
				{
					days++;
					replica2.add(Calendar.DAY_OF_YEAR, 1);
				}
				result = days;
			}
		}
		
		else
		{
			//System.out.println(calendar.getTime() + " is before " + calendar2.getTime());
			if(replica1.get(Calendar.YEAR) == replica2.get(Calendar.YEAR))
			{
				int val1 = replica1.get(Calendar.DAY_OF_YEAR);
				int val2 = replica2.get(Calendar.DAY_OF_YEAR);
				result = val1 - val2;
			}
			else
			{
				int days = 0;
				while(replica1.get(Calendar.YEAR) < replica2.get(Calendar.YEAR))
				{
					days++;
					replica1.add(Calendar.DAY_OF_YEAR, 1);
				}
			
				while(replica1.get(Calendar.DAY_OF_YEAR) < replica2.get(Calendar.DAY_OF_YEAR))
				{
					days++;
					replica1.add(Calendar.DAY_OF_YEAR, 1);
				}
				result = days * -1;
			}
		}
		return result;
	}
	
	public void insert(int val)
	{

		boolean exist = false;
		for(FourDValueSlot vs: intervals)
		{
			if(vs.getInterval() == val)
			{
				exist = true;
				vs.insert();
			}
		}
		
		if(!exist)
		{
			FourDValueSlot vs = new FourDValueSlot(val);
			intervals.add(vs);
		}
	}
	
	public int getAverageOccurance()
	{
		int temp = 0;
		for(FourDValueSlot vs: intervals)
		{
			temp = temp + vs.getOccurance();
		}
		
		int result = temp / intervals.size();
		return result;
	}
	
	public double getAverageInterval()
	{
		int sumOfInterval = 0;
		int sumOfOccurance = 0;
		for(FourDValueSlot vs: intervals)
		{
			sumOfInterval = sumOfInterval + (vs.getInterval() * vs.getOccurance());
			sumOfOccurance = sumOfOccurance + vs.getOccurance();
		}
		
		System.out.println("SumInt: " + sumOfInterval + " sumOc: " + sumOfOccurance);
		
		double result = (double)sumOfInterval / (double)sumOfOccurance;
		return result;
		
	}
	
	
	public double getPercentageforDay(GregorianCalendar date)
	{
		ValueSlot target = null;
		int average = getAverageOccurance();
		for(ValueSlot vs:matrix)
		{
			if(match(vs.getDate(), date))
			{
				target = vs;
			}
		}
		
		if(target == null)
		{
			return -1;
		}
		else
		{
			if(target.getOccurance() == 0)
			{
				return -2;
			}
			else
			{
				System.out.println("average is: " + average + ", and occurance for: " + target.getDate().getTime() + " is: " + target.getOccurance());
				double result = (double)average / (double)target.getOccurance();
				System.out.println("And percentage is: " + result);
				return result;
			}
		}
	}
	
	public String getPercentageString(GregorianCalendar date)
	{
		ValueSlot target = null;
		int average = getAverageOccurance();
		for(ValueSlot vs:matrix)
		{
			if(match(vs.getDate(), date))
			{
				target = vs;
			}
		}
		
		if(target == null)
		{
			return "non found";
		}
		else
		{
			if(target.getOccurance() == 0)
			{
				return "Occurance is 0";
			}
			else
			{
				//System.out.println("average is: " + average + ", and occurance for: " + target.getDate().getTime() + " is: " + target.getOccurance());
				double result = (double)average / (double)target.getOccurance();
				
				return "4D: average is: " + average + ", and occurance for: " + target.getDate().getTime() + " is: " + target.getOccurance() + "\nAnd percentage is: " + result + "\n";
			}
		}
	}

}
